# from ...addon.naming import FluidLabNaming
from ..ui_module_panel import FLUIDLAB_ModulePanel
from bpy.types import Panel, UILayout, Object, ParticleSettings
from ...properties.ui.props_toggles import FLUIDLAB_PG_toggles
from ...properties.fluid_forces.props_fluid_forces import FluidLab_PG_FluidForces
from ...properties.lists.props_list_fluid_forces import FluidForcesList
from ...properties.lists.props_list_fluid_emitters import FluidEmittersList
from ...libs.functions.get_common_vars import get_common_vars
from ...libs.functions.common_ui_elements import title_header, collapsable
from .ui_fluid_forces_animation import forces_anim_ui


def particles_force_field_settings_ui(layout, psys_settings, field):

    layout.use_property_split = True

    if not field or field.type == 'NONE':
        return

    flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)

    col = flow.column(align=True)
    
    col.prop(psys_settings, "effector_amount", text="Effector Amount")

    col.prop(field, "type", text="Type 1")

    if field.type == 'DRAG':
        col.prop(field, "linear_drag", text="Linear")
    else:
        col.prop(field, "strength")

    if field.type == 'TURBULENCE':
        col.prop(field, "size")
        col.prop(field, "flow")

    elif field.type == 'HARMONIC':
        col.prop(field, "harmonic_damping", text="Damping")
        col.prop(field, "rest_length")

    elif field.type == 'VORTEX' and field.shape != 'POINT':
        col.prop(field, "inflow")

    elif field.type == 'DRAG':
        col.prop(field, "quadratic_drag", text="Quadratic")

    else:
        col.prop(field, "flow")

    sub = col.column(heading="Affect")

    sub.prop(field, "apply_to_location", text="Location")
    sub.prop(field, "apply_to_rotation", text="Rotation")

    col = flow.column()
    sub = col.column(align=True)
    sub.prop(field, "noise", text="Noise Amount")
    sub.prop(field, "seed", text="Seed")

    if field.type == 'TURBULENCE':
        col.prop(field, "use_global_coords", text="Global")

    elif field.type == 'HARMONIC':
        col.prop(field, "use_multiple_springs")

    if field.type == 'FORCE':
        col.prop(field, "use_gravity_falloff", text="Gravitation")

    col.prop(field, "use_absorption")
    col.prop(field, "wind_factor")


def basic_force_field_settings_ui(layout, field):

    layout.use_property_split = True

    if not field or field.type == 'NONE':
        return
    
    layout.separator()

    layout.prop(field, "type", text="Type")
    layout.separator()

    if field.type not in {'NONE', 'GUIDE', 'TEXTURE'}:
        layout.prop(field, "shape", text="Shape")

    flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)
    
    if field.type == 'GUIDE':
        col = flow.column()
        col.prop(field, "guide_free")
        col.prop(field, "falloff_power")
        col.prop(field, "use_guide_path_add")
        col.prop(field, "use_guide_path_weight")

        col.separator()

        col = flow.column()
        col.prop(field, "guide_clump_amount", text="Clumping Amount")
        col.prop(field, "guide_clump_shape")

        col.separator()

        col.prop(field, "guide_minimum", text="Min Distance")

        col = layout.column(align=False, heading="Max Distance")
        col.use_property_decorate = False
        row = col.row(align=True)
        sub = row.row(align=True)
        sub.prop(field, "use_max_distance", text="")
        sub = sub.row(align=True)
        sub.active = field.use_max_distance
        sub.prop(field, "distance_max", text="")
        # row.prop_decorator(field, "distance_max")

    elif field.type == 'TEXTURE':
        col = flow.column()
 
        col.prop(field, "texture_mode")
        col.separator()

        col.prop(field, "strength")
        
        sub = col.column(heading="Affect")
        sub.prop(field, "apply_to_location", text="Location")
        
        col = flow.column()
         
        col.prop(field, "texture_nabla")
        col.prop(field, "use_object_coords")
        col.prop(field, "use_2d_force")

        col.row().template_ID(field, "texture", new="texture.new")
        

    elif field.type == 'FLUID_FLOW':
        col = flow.column()
        col.prop(field, "strength")
        col.prop(field, "flow")

        sub = col.column(heading="Affect")
        sub.prop(field, "apply_to_location", text="Location")
        sub.prop(field, "apply_to_rotation", text="Rotation")

        col = flow.column()
        col.prop(field, "source_object")
        col.prop(field, "use_smoke_density")
    
    else:

        col = flow.column(align=True)

        if field.type == 'DRAG':
            col.prop(field, "linear_drag", text="Linear")
        else:
            col.prop(field, "strength")

        if field.type == 'TURBULENCE':
            col.prop(field, "size")
            col.prop(field, "flow")

        elif field.type == 'HARMONIC':
            col.prop(field, "harmonic_damping", text="Damping")
            col.prop(field, "rest_length")

        elif field.type == 'VORTEX' and field.shape != 'POINT':
            col.prop(field, "inflow")

        elif field.type == 'DRAG':
            col.prop(field, "quadratic_drag", text="Quadratic")

        else:
            col.prop(field, "flow")
        

        sub = col.column(heading="Affect")

        sub.prop(field, "apply_to_location", text="Location")
        sub.prop(field, "apply_to_rotation", text="Rotation")

        col = flow.column()
        sub = col.column(align=True)
        sub.prop(field, "noise", text="Noise Amount")
        sub.prop(field, "seed", text="Seed")

        if field.type == 'TURBULENCE':
            col.prop(field, "use_global_coords", text="Global")

        elif field.type == 'HARMONIC':
            col.prop(field, "use_multiple_springs")

        if field.type == 'FORCE':
            col.prop(field, "use_gravity_falloff", text="Gravitation")

        col.prop(field, "use_absorption")
        col.prop(field, "wind_factor")


def basic_force_field_falloff_ui(layout, field, f_forces):

    if not field or field.type == 'NONE':
        return
    
    if f_forces.ff_sections != 'EMITTER':
        layout.prop(field, "falloff_type", text="Shape")

    col = layout.column(align=True)
    col.prop(field, "z_direction")
    col.prop(field, "falloff_power", text="Power")

    col = layout.column(align=False, heading="Min Distance")
    col.use_property_decorate = False
    row = col.row(align=True)
    sub = row.row(align=True)
    sub.prop(field, "use_min_distance", text="")
    sub = sub.row(align=True)
    sub.active = field.use_min_distance
    sub.prop(field, "distance_min", text="")
    # row.prop_decorator(field, "distance_min")

    col = layout.column(align=False, heading="Max Distance")
    col.use_property_decorate = False
    row = col.row(align=True)
    sub = row.row(align=True)
    sub.prop(field, "use_max_distance", text="")
    sub = sub.row(align=True)
    sub.active = field.use_max_distance
    sub.prop(field, "distance_max", text="")
    # row.prop_decorator(field, "distance_max")


def basic_force_field_kink(layout, field):
    layout.use_property_split = True
    layout.prop(field, "guide_kink_type", text="Type")

    layout.separator()

    if field.guide_kink_type != 'NONE':
        flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=True)

        col = flow.column(align=True)
        col.prop(field, "guide_kink_axis")
        col.prop(field, "guide_kink_frequency")

        col = flow.column(align=True)
        col.prop(field, "guide_kink_shape")
        col.prop(field, "guide_kink_amplitude")


def get_force_ob(f_forces:FluidLab_PG_FluidForces, forces_list:FluidForcesList, emitters_list:FluidEmittersList) -> Object:
    force_ob = None

    # Usando el listado de fuerzas para global:
    if f_forces.ff_sections == 'GLOBAL':

        if forces_list is None:
            return
        
        active_force = forces_list.active
        if not active_force:
            return
        
        force_ob = active_force.force
    
    # Usando el listado de fuerzas para Mesh:
    elif f_forces.ff_sections == 'MESH':
        
        if emitters_list is None:
            return
        
        if emitters_list.is_void:
            return
        
        active_emitter_item = emitters_list.active
        force_ob = active_emitter_item.emitter
    
    return force_ob


def has_ob_field(force_ob: Object) -> bool:
    return force_ob is not None and force_ob.field and force_ob.field.type != 'NONE'

def has_p_field(psys_settings: Object) -> bool:
    return psys_settings is not None and psys_settings.force_field_1 and psys_settings.force_field_1.type != 'NONE'


def force_field_ob_settings_ui(context, layout:UILayout, toggles:FLUIDLAB_PG_toggles, f_forces:FluidLab_PG_FluidForces, force_ob:Object) -> None:
    
    # Global force:

    if f_forces.ff_settings_animations != 'SETTINGS':
        return
    
    if force_ob is None:
        return

    if force_ob.name not in context.view_layer.objects:
        return
    
    if not has_ob_field(force_ob):
        return
    
    field = force_ob.field
    
    if field.type == 'NONE':
        return

    layout.separator()
    
    lay_settings = layout.column(align=True)
    lay_settings.use_property_split = True

    force_settings = collapsable(
        lay_settings,
        toggles,
        "force_settings",
        "Force Settings",
        'SETTINGS',
        align=True,
    )
    if force_settings:
        basic_force_field_settings_ui(force_settings, field)
    
    if field.type != 'GUIDE':
        force_falloff_settings = collapsable(
            lay_settings,
            toggles,
            "force_falloff_settings",
            "FallOff",
            'MOD_INSTANCE',
            align=True,
        )
        if force_falloff_settings:
            lay_settings.use_property_decorate = False
            basic_force_field_falloff_ui(force_falloff_settings, field, f_forces)
    else:
        force_kink = collapsable(
            lay_settings,
            toggles,
            "force_kink",
            "Kink",
            'GP_SELECT_BETWEEN_STROKES',
            align=True,
        )
        if force_kink:
            basic_force_field_kink(force_kink, field)



class FLUIDLAB_PT_fluid_forces_ui(Panel, FLUIDLAB_ModulePanel):
    fluidlab_section = 'FORCES'
    bl_idname = "FLUIDLAB_PT_fluid_forces_ui"
    bl_label = "Module"

    def draw(self, context):

        forces_list = None
        ff_active_group = None
        emitters_list = None

        fluidlab, fluid_groups, fluid_forces_groups, ui, toggles = get_common_vars(context, get_fluidlab=True, get_fluid_groups=True, get_fluid_forces_groups=True, get_ui=True, get_toggles=True)
        f_forces = fluidlab.fluid_forces

        active_group = fluid_groups.active
        ff_active_group = fluid_forces_groups.active

        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False

        col = layout.column(align=True)
        title_header(col, "Forces")

        main_col = col.box().column(align=True)
        main_col.use_property_split = True
        main_col.use_property_decorate = False

        if ff_active_group is not None:
            forces_list = ff_active_group.forces
        
        if active_group is not None:
            emitters_list = active_group.emitters
        
        force_ob = get_force_ob(f_forces, forces_list, emitters_list)

        # -------------------------------------------------------------------------------
        # ## UI BASICA ##
        # ------------------------------------------------------------------------------- 
        if ui.ui_mode == 'BASIC':
            main_col.label(text="Hola Mundo Basico")

    
        # -------------------------------------------------------------------------------
        # ## UI AVANZADA ##
        # ------------------------------------------------------------------------------- 
        elif ui.ui_mode == 'ADVANCED':

            main_col.use_property_split = False
            
            sections = main_col.row(align=True)
            sections.scale_y = 1.3
            sections.prop(f_forces, "ff_sections", expand=True)

            if f_forces.ff_sections == 'GLOBAL':
                main_col.separator()

                lists_row = main_col.row(align=True)

                left_col = lists_row.column(align=True)
                right_col = lists_row.column(align=True)
                
                left_title_col = left_col.box().row(align=True)
                left_title_col.alignment = 'CENTER'
                left_title_col.label(text="Forces Groups")

                left_col.template_list("FLUIDLAB_UL_draw_fluids_froces_groups", "", fluid_forces_groups, "list", fluid_forces_groups, "list_index", rows=3)
                
                add_grp_bt = left_col.row(align=True)
                add_grp_bt.scale_y = 1.3
                add_grp_bt.operator("fluidlab.fluid_forces_groups_list_add", text="Add Group")

                add_grp_bt.operator("fluidlab.force_groups_list_item_move", icon='TRIA_UP', text="").direction = 'UP'
                add_grp_bt.operator("fluidlab.force_groups_list_item_move", icon='TRIA_DOWN', text="").direction = 'DOWN'

                dropdown = add_grp_bt.row(align=True)
                dropdown.enabled = not fluid_forces_groups.is_void
                dropdown.menu("FLUIDLAB_MT_force_groups_list_submenu", text="", icon='DOWNARROW_HLT')

                right_title_col = right_col.box().row(align=True)
                right_title_col.alignment = 'CENTER'
                right_title_col.label(text="Forces")

                if forces_list is not None:
                    right_col.template_list("FLUIDLAB_UL_draw_fluids_froces", "", forces_list, "list", forces_list, "list_index", rows=3)

                    add_frc_bt = right_col.row(align=True)
                    add_frc_bt.scale_y = 1.3
                    add_frc_bt.operator("fluidlab.fluid_force_list_add", text="Add Force")

                    add_frc_bt.operator("fluidlab.force_groups_forces_list_item_move", icon='TRIA_UP', text="").direction = 'UP'
                    add_frc_bt.operator("fluidlab.force_groups_forces_list_item_move", icon='TRIA_DOWN', text="").direction = 'DOWN'

                    dropdown = add_frc_bt.row(align=True)
                    dropdown.enabled = not forces_list.is_void
                    dropdown.menu("FLUIDLAB_MT_force_groups_forces_list_submenu", text="", icon='DOWNARROW_HLT')
        
                else:
                    fake_group_list = right_col.box()
                    fake_group_list.scale_y = 3.5
                    fake_group_list.scale_x = 1.1
                    fake_group_list.label(text=" ")

                    add_fake_bt = right_col.row(align=True)
                    add_fake_bt.scale_y = 1.3
                    add_fake_bt.enabled = False
                    add_fake_bt.prop(ui, "fake_button", text="Add Force", toggle=True)

                    add_fake_bt.operator("fluidlab.force_groups_forces_list_item_move", icon='TRIA_UP', text="").direction = 'UP'
                    add_fake_bt.operator("fluidlab.force_groups_forces_list_item_move", icon='TRIA_DOWN', text="").direction = 'DOWN'

                    dropdown = add_fake_bt.row(align=True)
                    dropdown.enabled = False
                    dropdown.menu("FLUIDLAB_MT_force_groups_forces_list_submenu", text="", icon='DOWNARROW_HLT')
                
                main_col.separator()

                # Settings / Animattion toggle:
                sub_sections = main_col.row(align=True)
                sub_sections.scale_y = 1.3
                sub_sections.prop(f_forces, "ff_settings_animations", expand=True)

                if f_forces.ff_settings_animations == 'SETTINGS':
                    force_field_ob_settings_ui(context, main_col, toggles, f_forces, force_ob)
                
                elif f_forces.ff_settings_animations == 'ANIMATION':
                    forces_anim_ui(context, main_col, f_forces, force_ob)
                
            
            elif f_forces.ff_sections == 'EMITTER':

                if emitters_list:
    
                    main_col.separator()
                    emitter_item = emitters_list.active
                    if emitter_item:
                        
                        emitter_ob = next((ob for ob in emitter_item.group_coll.objects if ob.fluidlab.id_name == "Emitter_"+ emitter_item.id_name ), None)
                        if emitter_ob:

                            main_col.box().label(text=f"Working with: {emitter_ob.name}", icon='INFO')
                            main_col.separator()
                    
                            psys = emitter_ob.particle_systems.active
                            psys_settings = psys.settings
                            have_p_field = has_p_field(psys_settings)

                            button = main_col.row(align=True)
                            button.scale_y = 1.3

                            if not have_p_field:
                                button.operator("fluidlab.forces_particles_add", text="Add Particle Force")
                            else:
                                button.alert = True
                                button.operator("fluidlab.forces_particles_rm", text="Remove Particle Force", icon='TRASH')

                                main_col.separator()

                                # Settings / Animattion toggle:
                                sub_sections = main_col.row(align=True)
                                sub_sections.scale_y = 1.3
                                sub_sections.prop(f_forces, "ff_settings_animations", expand=True)

                                if f_forces.ff_settings_animations == 'SETTINGS':

                                    field = psys_settings.force_field_1
                                    if field:
                                        
                                        main_col.separator()

                                        # funciones tomadas prestadas de blender y adaptadas 
                                        # (4.0/scripts/startup/bl_ui/properties_physics_common.py):
                                        force_p_settings = collapsable(
                                            main_col,
                                            toggles,
                                            "force_p_settings",
                                            "Force Settings",
                                            'SETTINGS',
                                            align=True,
                                        )
                                        if force_p_settings:
                                            particles_force_field_settings_ui(force_p_settings, psys_settings, field)
                                        
                                        if field.type != 'GUIDE' or f_forces.ff_sections == 'EMITTER':

                                            # si es de EMITTER (particulas) las particulas usan el falloff normal (no el kink) y sin shape: 
                                            force_p_falloff_settings = collapsable(
                                                main_col,
                                                toggles,
                                                "force_p_falloff_settings",
                                                "FallOff",
                                                'MOD_INSTANCE',
                                                align=True,
                                            )
                                            if force_p_falloff_settings:
                                                force_p_falloff_settings.use_property_split = True
                                                basic_force_field_falloff_ui(force_p_falloff_settings, field, f_forces)
                                        else:
                                            force_p_kink = collapsable(
                                                main_col,
                                                toggles,
                                                "force_kink",
                                                "Kink",
                                                'GP_SELECT_BETWEEN_STROKES',
                                                align=True,
                                            )
                                            if force_p_kink:
                                                basic_force_field_kink(force_p_kink, field)

                                elif f_forces.ff_settings_animations == 'ANIMATION':
                                    forces_anim_ui(context, main_col, f_forces, emitter_ob)


            elif f_forces.ff_sections == 'COLLIDERS':
                
                fluid_single_colliders, toggles = get_common_vars(context, get_fluid_single_colliders=True, get_toggles=True)
                active_collider = fluid_single_colliders.active
                if not active_collider:
                    return

                main_col.template_list("FLUIDLAB_UL_draw_fluids_single_colliders", "", fluid_single_colliders, "list", fluid_single_colliders, "list_index", rows=3)

                if active_collider:

                    # Aquí pasa igual que con el listado de dinamic paint.
                    collider_ob = active_collider.collider
                    
                    field = collider_ob.field
                    main_col.box().label(text=f"Working with: {active_collider.label_txt}", icon='INFO')
                    main_col.separator()

                    buttton = main_col.row(align=True)
                    buttton.scale_y = 1.3

                    if field.type == 'NONE':
                        buttton.operator("fluidlab.forces_collliders_add")
                    else:
                        buttton.alert = True
                        buttton.operator("fluidlab.forces_collliders_rm")

                        # Settings / Animattion toggle:
                        main_col.separator()
                        sub_sections = main_col.row(align=True)
                        sub_sections.scale_y = 1.3
                        sub_sections.prop(f_forces, "ff_settings_animations", expand=True)

                        if f_forces.ff_settings_animations == 'SETTINGS':
                            
                            main_col.separator()

                            # funciones tomadas prestadas de blender y adaptadas 
                            # (4.0/scripts/startup/bl_ui/properties_physics_common.py):
                            force_c_settings = collapsable(
                                main_col,
                                toggles,
                                "force_c_settings",
                                "Force Settings",
                                'SETTINGS',
                                align=True,
                            )
                            if force_c_settings:
                                basic_force_field_settings_ui(force_c_settings, field)
                            
                            if field.type != 'GUIDE':
                                force_c_falloff_settings = collapsable(
                                    main_col,
                                    toggles,
                                    "force_c_falloff_settings",
                                    "FallOff",
                                    'MOD_INSTANCE',
                                    align=True,
                                )
                                if force_c_falloff_settings:
                                    force_c_falloff_settings.use_property_split = True
                                    basic_force_field_falloff_ui(force_c_falloff_settings, field, f_forces)
                            else:
                                force_c_kink = collapsable(
                                    main_col,
                                    toggles,
                                    "force_kink",
                                    "Kink",
                                    'GP_SELECT_BETWEEN_STROKES',
                                    align=True,
                                )
                                if force_c_kink:
                                    basic_force_field_kink(force_c_kink, field)

                        elif f_forces.ff_settings_animations == 'ANIMATION':
                            forces_anim_ui(context, main_col, f_forces, collider_ob)